home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCFSRC.PAK / OCAPP.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  30KB  |  1,269 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectComponents
  3. // Copyright (c) 1994, 1997 by Borland International, All Rights Reserved
  4. //
  5. // $Revision:   2.18  $
  6. //
  7. //   Implementation of TOcApp Class
  8. //----------------------------------------------------------------------------
  9. #include <ocf/pch.h>
  10. #if !defined(OCF_AUTODEFS_H)
  11. # include <ocf/autodefs.h>
  12. #endif
  13. #if !defined(OCF_APPDESC_H)
  14. # include <ocf/appdesc.h>
  15. #endif
  16. #if !defined(OCF_OCREG_H)
  17. #include <ocf/ocreg.h>
  18. #endif
  19. #if !defined(OCF_OCAPP_H)
  20. # include <ocf/ocapp.h>
  21. #endif
  22. #if !defined(OCF_OCPART_H)
  23. # include <ocf/ocpart.h>
  24. #endif
  25. #if !defined(SERVICES_MEMORY_H)
  26. # include <services/memory.h>
  27. #endif
  28. #if defined(BI_PLAT_WIN32)
  29. # include <winver.h>
  30. #elif defined(BI_PLAT_WIN16)
  31. # include <ver.h>
  32. #endif
  33.  
  34. DIAG_DEFINE_GROUP(OcApp, true, 1);
  35. DIAG_DECLARE_GROUP(OcDll);
  36. DIAG_DECLARE_GROUP(OcRefCount);
  37.  
  38. //
  39. // Compatibility constructor & SetupWindow for TOcApp
  40. //
  41. TOcApp::TOcApp(TOcRegistrar& registrar, uint32 options, TOcApp*& retOcApp)
  42. :
  43.   Host(0),
  44.   FrameHost(new TOcAppFrameHostMsg(this)), // Use default, msg based host
  45.   OcAppPtr(&retOcApp),
  46.   Options(options),
  47.   DisableDlgs(false),
  48.   Registrar(registrar),
  49.   Registered(false)
  50. {
  51.   Registrar.AppCount++;
  52.   Init();
  53.   RegisterClasses();
  54.  
  55.   *OcAppPtr = this;    // Setup the client's pointer last if all else is OK
  56.   TRACEX(OcRefCount, 1, "TOcApp() @" << (void*)this);
  57.  
  58.   // Host = (char*)OcAppPtr - int(&(TOcModule*)0->OcAppPtr);
  59. }
  60.  
  61. //
  62. void TOcApp::SetupWindow(HWND frameWnd)
  63. {
  64.   FrameHost->SetWindow(frameWnd);  // Pass frame's hWnd over to frame host
  65.  
  66.   Registrar.SetApp(this);
  67. }
  68.  
  69. //
  70. // New constructor for TOcApp using host interfaces
  71. //
  72. TOcApp::TOcApp(TOcRegistrar& registrar, uint32 options, TOcAppHost* host,
  73.                TOcAppFrameHost* frameHost)
  74. :
  75.   Host(host),
  76.   FrameHost(frameHost),
  77.   OcAppPtr(0),
  78.   Options(options),
  79.   DisableDlgs(false),
  80.   Registrar(registrar),
  81.   Registered(false)
  82. {
  83.   PRECONDITION(&host);
  84.   PRECONDITION(&frameHost);
  85.  
  86.   Registrar.AppCount++;
  87.   Init();
  88.   RegisterClasses();
  89.  
  90.   if (Host)
  91.     Host->AttachHost(this);
  92.  
  93.   TRACEX(OcRefCount, 1, "TOcApp() @" << (void*)this);
  94. }
  95.  
  96. //
  97. void TOcApp::SetupWindow(TOcAppFrameHost* frameHost)
  98. {
  99.   FrameHost = frameHost;
  100. }
  101.  
  102. //
  103. // Common constructor initialization
  104. //
  105. void
  106. TOcApp::Init()
  107. {
  108.   // Initialize BOle service ptrs that may or may not get setup later
  109.   //
  110.   BService = 0;
  111.   BServiceI = 0;
  112.  
  113.   AddRef();  // TUnknown defaults to 0, we need 1
  114.  
  115.   // Create a BOle class manager for this app
  116.   //
  117.   BCmI = Registrar.CreateBOleClassMgr();
  118.  
  119.   // Create BOle service object & get its interface
  120.   //
  121.   BOleComponentCreate(&BService, GetOuter(), cidBOleService);
  122.   if (BService && HRSucceeded(BService->QueryInterface(IID_IBService2,
  123.                                                        &(LPVOID)BServiceI))) {
  124.     Release();
  125.     BServiceI->Init(this);
  126.   }
  127.   else
  128.     TXObjComp::Throw(TXObjComp::xBOleBindFail); // give up if no IBService2
  129.  
  130. #if defined(BI_PLAT_WIN16)
  131.   // Make this task's message queue larger for Ole.
  132.   // This is necessary for all Win16 apps requiring LRPC calls.
  133.   //
  134.   int queueSize = 96;
  135.   while (!::SetMessageQueue(queueSize) && queueSize > 0)
  136.     queueSize -= 8;
  137. #endif
  138.  
  139.   // Get the clipboard format strings
  140.   //
  141.   for (uint i = IDS_CFFIRST; i <= IDS_CFLAST; i++) {
  142.     char name[128];
  143.     if (::FindResource(_hInstance, MAKEINTRESOURCE(i/16+1), RT_STRING)) {
  144.       if (::LoadString(_hInstance, i, name, 128)) {
  145.         char* resultName = strchr(name, '\n');
  146.         *resultName++ = 0;
  147.         NameList.Add(new TOcFormatName(name, resultName));
  148.       }
  149.     }
  150.   }
  151.  
  152.   // Get & copy the appname from the reginfo
  153.   //
  154.   Name = Registrar.GetAppDescriptor().GetAppName(LangSysDefault);
  155. }
  156.  
  157. //
  158. // Clean up this object be releasing all helpers.
  159. //
  160. TOcApp::~TOcApp()
  161. {
  162.   // We're gone, make sure nobody calls us through unref'd ptr
  163.   //
  164.   if (OcAppPtr)     
  165.     *OcAppPtr = 0;
  166.   if (Host) {
  167.     Host->ReleaseOcObject();
  168.     Host = 0;
  169.   }
  170.  
  171.   UnregisterClasses();
  172.  
  173.   // RefCnt was held by controller
  174.   //
  175.   if (FrameHost) {
  176.     if (FrameHost->EvOcAppShutdown() &&
  177.         IsOptionSet(amServedApp) && !IsOptionSet(amExeModule)) {
  178.       Registrar.Shutdown(0, Options);
  179.     }
  180.     FrameHost->ReleaseOcObject();
  181.     FrameHost = 0;
  182.   }
  183.  
  184.   if (BService)
  185.     BService->Release();
  186.   Registrar.AppCount--;
  187.   if (BCmI)
  188.     BCmI->Release();
  189. }
  190.  
  191. //
  192. // Should only be called by the owner/creator of this object
  193. //
  194. void
  195. TOcApp::ReleaseObject()
  196. {
  197.   if (Host) {
  198.     Host->ReleaseOcObject();
  199.     Host = 0;
  200.   }
  201.   if (FrameHost) {
  202.     FrameHost->ReleaseOcObject();
  203.     FrameHost = 0;
  204.   }
  205.   if (!IsOptionSet(amServedApp))
  206.     Release();   // if our container app holds the refcnt, then release it
  207. }
  208.  
  209. //
  210. // Callback from TUnknown's implementation of QueryInterface
  211. //
  212. HRESULT
  213. TOcApp::QueryObject(const IID far& iid, void far* far* iface)
  214. {
  215.   HRESULT hr;
  216.  
  217.   // interfaces
  218.      SUCCEEDED(hr = IBApplication_QueryInterface(this, iid, iface))
  219.   || SUCCEEDED(hr = IBClassMgr_QueryInterface(this, iid, iface))
  220.  
  221.   // helpers
  222.   || (BService && SUCCEEDED(hr = BService->QueryInterface(iid, iface)))
  223.   ;
  224.   return hr;
  225. }
  226.  
  227. //----------------------------------------------------------------------------
  228.  
  229. //
  230. // Create a BOle helper for one of our OC objects in this app
  231. //
  232. HRESULT
  233. TOcApp::BOleComponentCreate(IUnknown far* far* iface, IUnknown* outer, BCID idClass)
  234. {
  235.   return BCmI->ComponentCreate(iface, outer, idClass);
  236. }
  237.  
  238. //----------------------------------------------------------------------------
  239. // Runtime document factory registration
  240.  
  241. //
  242. // Register doc factories based on their 'progid' and their templates
  243. //
  244. void
  245. TOcApp::RegisterClasses()
  246. {
  247.   if (Registered)
  248.     return;
  249.  
  250.   // No class registration for InProc Servers
  251.   //
  252.   if (!(IsOptionSet(amExeModule)))
  253.     return;
  254.  
  255.   // No class registration for single use apps unless embedded
  256.   //
  257.   if (IsOptionSet(amSingleUse) &&
  258.      (IsOptionSet(amAutomation)|| !IsOptionSet(amEmbedding)))
  259.     return;
  260.  
  261.   // Loop thru all templates, registering registerable classes
  262.   //
  263.   const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  264.   for ( ; link; link = link->GetNext()) {
  265.     TRegList&   regList = link->GetRegList();
  266.     const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  267.     if (progid) {
  268.  
  269.       // Don't register container classes unless embedding
  270.       //
  271.       if (!IsOptionSet(amEmbedding) &&
  272.           !(const char*)regList["insertable"])
  273.         continue;
  274.  
  275.       bool multiUse = !IsOptionSet(amSingleUse);
  276.       if (multiUse) {
  277.         const char* usage = regList.Lookup("usage");
  278.         char su[] = ocrSingleUse;
  279.         multiUse = ToBool(!(usage && *usage == *su));
  280.       }
  281.       if (!RegisterClass(progid, reinterpret_cast<BCID>(link), multiUse))
  282.         TXObjComp::Throw(TXObjComp::xDocFactoryFail);
  283.     }
  284.   }
  285.   Registered = true;
  286. }
  287.  
  288. //
  289. // Unregister doc class factories based on their 'progid' and their templates
  290. //
  291. void
  292. TOcApp::UnregisterClasses()
  293. {
  294.   if (!Registered)
  295.     return;
  296.  
  297.   // Loop thru all templates, unregistering registerable classes
  298.   //
  299.   const TRegLink* link = GetRegistrar().GetAppDescriptor().GetRegLinkHead();
  300.   for ( ; link; link = link->GetNext()) {
  301.     TRegList& regList = link->GetRegList();
  302.     const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  303.     if (progid)
  304.       if (!UnregisterClass(progid))
  305.         TXObjComp::Throw(TXObjComp::xDocFactoryFail);
  306.   }
  307.   Registered = false;
  308. }
  309.  
  310. //
  311. // Add a user defined clipboard format name
  312. //
  313. void
  314. TOcApp::AddUserFormatName(const char* name, const char* resultName, const char* id)
  315. {
  316.   NameList.Add(new TOcFormatName(name, resultName, id));
  317. }
  318.  
  319.  
  320. //----------------------------------------------------------------------------
  321. // OC side exposure of selected IBService functions
  322.  
  323. bool
  324. TOcApp::UnregisterClass(const string& className)
  325. {
  326.   if (BServiceI)
  327.     return HRSucceeded(BServiceI->UnregisterClass(OleStr(className.c_str())));
  328.   return false;
  329. }
  330.  
  331. //
  332. // Let BOle know that the main window has resized. In-place servers may need to
  333. // adjust their toolbars
  334. //
  335. void
  336. TOcApp::EvResize()
  337. {
  338.   if (BServiceI)
  339.     BServiceI->OnResize();
  340. }
  341.  
  342. //
  343. // Let BOle know that the main window has [de]activated.
  344. //
  345. void
  346. TOcApp::EvActivate(bool active)
  347. {
  348.   if (BServiceI)
  349.     BServiceI->OnActivate(active);
  350. }
  351.  
  352. bool
  353. TOcApp::RegisterClass(const string& className, BCID classId, bool multiUse)
  354. {
  355.   // Self-embedding works only if the app is multi-use
  356.   //
  357.   if (BServiceI)
  358.     return HRSucceeded(BServiceI->RegisterClass(OleStr(className.c_str()),
  359.                        this, classId, ToBool(multiUse), ToBool(!multiUse)));
  360.   return false;
  361. }
  362.  
  363. bool
  364. TOcApp::CanClose()
  365. {
  366.   return BServiceI ? HRIsOK(BServiceI->CanClose()) : true;  // there are no servers running
  367. }
  368.  
  369. uint
  370. TOcApp::EnableEditMenu(TOcMenuEnable menuEnable, IBDataConsumer* ocView)
  371. {
  372.   return BServiceI ? BServiceI->EnableEditMenu(menuEnable, ocView) : 0;
  373. }
  374.  
  375. bool
  376. TOcApp::Browse(TOcInitInfo& init)
  377. {
  378.   return BServiceI ? HRIsOK(BServiceI->Browse(&init)) : false;
  379. }
  380.  
  381. bool
  382. TOcApp::BrowseControls(TOcInitInfo& init)
  383. {
  384.   return BServiceI ? HRIsOK(BServiceI->BrowseControls(&init)) : false;
  385. }
  386.  
  387. bool
  388. TOcApp::BrowseClipboard(TOcInitInfo& init)
  389. {
  390.   return BServiceI ? HRIsOK(BServiceI->BrowseClipboard(&init)): false;
  391. }
  392.  
  393. bool
  394. TOcApp::Paste(TOcInitInfo& init)
  395. {
  396.   return BServiceI ? HRIsOK(BServiceI->Paste(&init)) : false;
  397. }
  398.  
  399. //
  400. // Copy Selected embedded object
  401. //
  402. bool
  403. TOcApp::Copy(TOcPart* ocPart)
  404. {
  405.   IBPart* bPartI;
  406.   if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, &(LPVOID)bPartI))) {
  407.     ocPart->Release();
  408.  
  409.     // Copy part with delayed rendering done by Bolero
  410.     //
  411.     return BServiceI ? HRIsOK(BServiceI->Clip(bPartI, true, true, true)) : false;
  412.   }
  413.   return false;
  414. }
  415.  
  416. //
  417. // Copy a selection in server document
  418. //
  419. bool
  420. TOcApp::Copy(TOcDataProvider* ocData)
  421. {
  422.   PRECONDITION(ocData);
  423.   if (BServiceI)
  424.     BServiceI->Clip(0, false, false, false);
  425.   else
  426.     return false;
  427.  
  428. #if   0
  429.   IBDataProvider far* bDataI;
  430.   if (ocData && SUCCEEDED(ocData->QueryInterface(IID_IBDataProvider, &(LPVOID)bDataI))) {
  431.     ocData->Release();
  432.  
  433.     // Copy part with delayed rendering done by ocDataProvider
  434.     //
  435.     return HRIsOK(BServiceI->Clip(bDataI, true, true, false));
  436.   }
  437.   return false;
  438. #endif
  439.  
  440.   return HRIsOK(BServiceI->Clip(ocData, true, true, false));
  441. }
  442.  
  443. //
  444. // Drag a selection
  445. //
  446. bool
  447. TOcApp::Drag(TOcDataProvider* ocData, TOcDropAction inAction, TOcDropAction& outAction)
  448. {
  449.   PRECONDITION(ocData);
  450.  
  451. #if   0
  452.   if (!BServiceI)
  453.     return false;
  454.  
  455.   IBDataProvider far* bDataI;
  456.   if (ocData && SUCCEEDED(ocData->QueryInterface(IID_IBDataProvider, &(LPVOID)bDataI))) {
  457.     ocData->Release();
  458.     return HRSucceeded(BServiceI->Drag(ocData, inAction, &outAction));
  459.   }
  460.   return false;
  461. #endif
  462.  
  463.   return BServiceI? HRSucceeded(BServiceI->Drag(ocData, inAction, &outAction)) : false;
  464. }
  465.  
  466. //
  467. // Drag an embedded object
  468. //
  469. bool
  470. TOcApp::Drag(TOcPart* ocPart, TOcDropAction inAction, TOcDropAction& outAction)
  471. {
  472.   IBPart far* bPartI;
  473.   if (ocPart && SUCCEEDED(ocPart->QueryInterface(IID_IBPart, &(LPVOID)bPartI))) {
  474.     ocPart->Release();
  475.     // Drag part with delayed rendering done by Bolero
  476.     //
  477.     return HRSucceeded(BServiceI->Drag(bPartI, inAction, &outAction));
  478.   }
  479.   return false;
  480. }
  481.  
  482. //
  483. // Open the Convert dialog, and perform the conversion if OK. return true if
  484. // conversion was perfromed successfully.
  485. //
  486. bool
  487. TOcApp::Convert(TOcPart* ocPart, bool b)
  488. {
  489.   PRECONDITION(ocPart);
  490.  
  491.   if (BServiceI == 0)
  492.     return false;
  493.  
  494.   // The Convert dialog is split into two pieces: one to run the dialog box
  495.   // and one to do the actual work. This way, the caller can record the
  496.   // actions of the dialog box for playback later.
  497.   //
  498.   TOcConvertInfo ci;
  499.   if (HRIsOK(BServiceI->ConvertUI(ocPart->GetBPartI(), b, &ci)))
  500.     return HRSucceeded(BServiceI->ConvertGuts(ocPart->GetBPartI(), b, &ci));
  501.  
  502.   return false;
  503. }
  504.  
  505. //----------------------------------------------------------------------------
  506. // IBApplication implementation
  507.  
  508. //
  509. // Return the application's name
  510. //
  511. LPCOLESTR _IFUNC
  512. TOcApp::GetAppName()
  513. {
  514.   return Name;
  515. }
  516.  
  517. TOcHelp _IFUNC
  518. TOcApp::HelpMode(TOcHelp /*newMode*/)
  519. {
  520.   // No built in help support
  521.   //
  522.   return hlpExit;
  523. }
  524.  
  525. //
  526. // Insert the container's menus into a provided menubar
  527. //
  528. HRESULT _IFUNC
  529. TOcApp::InsertContainerMenus(HMENU hMenu, TOcMenuWidths far* omw)
  530. {
  531.   PRECONDITION(omw);
  532.   if (!hMenu)
  533.     return HR_NOERROR;
  534.  
  535.   TOcMenuDescr md;
  536.   md.HMenu = hMenu;
  537.  
  538.   int i;
  539.   for (i = 0; i < 6; i++) {
  540.     md.Width[i] = (int)omw->Width[i] = 0;  // make sure the server's are zeroed
  541.     i++;
  542.     md.Width[i] = (int)omw->Width[i];
  543.   }
  544.  
  545.   if (!FrameHost || !FrameHost->EvOcAppInsMenus(md))
  546.     return HR_FAIL;
  547.  
  548.   for (i = 0; i < 6; i++)
  549.     omw->Width[i] = md.Width[i];
  550.  
  551.   return HR_NOERROR;
  552. }
  553.  
  554. //
  555. // Now set the provided menubar into the container's main frame window
  556. //
  557. HRESULT _IFUNC
  558. TOcApp::SetFrameMenu(HMENU hMenu)
  559. {
  560.   TOcMenuDescr md;
  561.   md.HMenu = hMenu;
  562.   return HRFailIfZero(FrameHost && FrameHost->EvOcAppMenus(md));
  563. }
  564.  
  565. //
  566. //
  567. //
  568. HRESULT _IFUNC
  569. TOcApp::Accelerator(MSG* msg)
  570. {
  571.   PRECONDITION(msg);
  572.  
  573.   return HRFailIfZero(FrameHost && FrameHost->EvOcAppProcessMsg(msg));
  574. }
  575.  
  576. //
  577. // Let BOle know if we (container app) have an accelerator table
  578. //
  579. HRESULT _IFUNC
  580. TOcApp::GetAccelerators(HACCEL far* phAccel, int far* pcAccel)
  581. {
  582.   TOcGetAccel acc;
  583.   if (FrameHost) {
  584.     if (FrameHost->EvOcAppGetAccel(&acc)) {
  585.       *phAccel = acc.Accel;
  586.       *pcAccel = acc.Count;
  587.       return HR_NOERROR;
  588.     }
  589.   }
  590.   return HR_FAIL;  // would retrieve or generate an accelerator table here
  591. }
  592.  
  593. //
  594. // Let BOle know if this app can/will accept links
  595. //
  596. HRESULT _IFUNC
  597. TOcApp::CanLink()
  598. {
  599.   return HR_OK;  // return HR_FAIL to disallow Linking
  600. }
  601.  
  602. //
  603. // Let BOle know if this app can/will accept embeddings
  604. //
  605. HRESULT _IFUNC
  606. TOcApp::CanEmbed()
  607. {
  608.   return HR_OK;  // return HR_FAIL to disallow Embedding
  609. }
  610.  
  611. //
  612. // Get and return the app frame's HWND
  613. //
  614. HWND _IFUNC
  615. TOcApp::GetWindow()
  616. {
  617.   return FrameHost ? FrameHost->EvOcGetWindow() : 0;
  618. }
  619.  
  620. //
  621. // Get client rectangle of app's main frame window
  622. //
  623. HRESULT _IFUNC
  624. TOcApp::GetWindowRect(TRect* r)
  625. {
  626.   PRECONDITION(r);
  627.  
  628.   return HRFailIfZero(FrameHost && FrameHost->EvOcAppFrameRect(r));
  629. }
  630.  
  631. //
  632. // Return the app's title, same as GetAppName()
  633. //
  634. LPCOLESTR _IFUNC
  635. TOcApp::GetWindowTitle()
  636. {
  637.   return Name;
  638. }
  639.  
  640. //
  641. // The server is asking for space along the app borders to put toolbars, etc.
  642. // This call is used to determine whether the container is willing and able to
  643. // provide a given combination.
  644. //
  645. HRESULT _IFUNC
  646. TOcApp::RequestBorderSpace(const TRect* space)
  647. {
  648.   TRect* nc_space = CONST_CAST(TRect*, space);  
  649.   return HRFailIfZero(FrameHost && FrameHost->EvOcAppBorderSpaceReq(nc_space));
  650. }
  651.  
  652. //
  653. // Now, actually provide the space along the app frame borders for inplace
  654. // server adornments
  655. //
  656. HRESULT _IFUNC
  657. TOcApp::SetBorderSpace(const TRect* space)
  658. {
  659.   TRect far* nc_space = CONST_CAST(TRect*, space);  
  660.   return HRFailIfZero(FrameHost && FrameHost->EvOcAppBorderSpaceSet(nc_space));
  661. }
  662.  
  663. //
  664. // Append supplied Ole title to frame's title, saving old title
  665. //
  666. void _IFUNC
  667. TOcApp::AppendWindowTitle(LPCOLESTR /*title*/)
  668. {
  669. }
  670.  
  671. //
  672. // Pass status bar text to container app to have app display it
  673. //
  674. HRESULT _IFUNC
  675. TOcApp::SetStatusText(LPCOLESTR text)
  676. {
  677.   // Convert OLE str into ANSI
  678.   //
  679.   if (FrameHost) {
  680.     FrameHost->EvOcAppStatusText(OleStr(text));
  681.     return HR_OK;
  682.   }
  683.   return HR_FAIL;
  684. }
  685.  
  686. //
  687. // Respond to let BOle know if our app is MDI or not
  688. //
  689. HRESULT _IFUNC
  690. TOcApp::IsMDI()
  691. {
  692.   // Since this flag is used only to do toolbar negotiation,
  693.   // we're always MDI as far as BOle is concerned.
  694.   //
  695.   return HR_NOERROR;
  696. }
  697.  
  698. //
  699. // The server is entering or leaving a modal state. Keep track so that we don't
  700. // interfere when it is modal.
  701. //
  702. HRESULT _IFUNC
  703. TOcApp::OnModalDialog(BOOL svrModal)
  704. {
  705.   DisableDlgs = (bool)svrModal;
  706.   return HR_NOERROR;
  707. }
  708.  
  709. //
  710. // The in-place server is done. Tell the container to restore its normal UI.
  711. // We can handle the window text here, let the app do the rest.
  712. //
  713. void _IFUNC
  714. TOcApp::RestoreUI()
  715. {
  716.   SetStatusText(0);
  717.   if (FrameHost)
  718.     FrameHost->EvOcAppRestoreUI();
  719. }
  720.  
  721. //
  722. //
  723. //
  724. void _IFUNC
  725. TOcApp::DialogHelpNotify(TOcDialogHelp help)
  726. {
  727.   if (FrameHost)
  728.     FrameHost->EvOcAppDialogHelp(help);
  729. }
  730.  
  731. //
  732. // Called by BOle when last embedding is closed
  733. // If that's the only reason the app is up we need to shut ourselves down
  734. //
  735. void _IFUNC
  736. TOcApp::ShutdownMaybe()
  737. {
  738.   TRACEX(OcApp, 1,
  739.          "ShutdownMaybe() on " << (void*)this <<
  740.          " Embedding:" << (int)ToBool(IsOptionSet(amEmbedding)) <<
  741.          " Win:" << hex << (uint)GetWindow());
  742.  
  743.   // Check first to see if TOcApp should initiate a shutdown
  744.   //
  745.   if (!FrameHost || FrameHost->EvOcAppShutdown() || !GetWindow()) {
  746.     // The server initiated the shutdown
  747.     //
  748.     if (!IsOptionSet(amExeMode)) {  // DLL server
  749.       AddRef();    // Prevent destroying ourselves yet
  750.       Registrar.Shutdown(&(IUnknown&)*this, Options);
  751.       Release();   // This should do us in now
  752.     }
  753.   }
  754. }
  755.  
  756. //----------------------------------------------------------------------------
  757. // Obsolete hard-wired message sending functions.
  758. // Use individual FrameHost methods instead
  759. //
  760.  
  761. #if   0
  762. uint32
  763. TOcApp::ForwardEvent(int eventId, const void far* param)
  764. {
  765.   if (::IsWindow(GetWindow()))
  766.     return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, (LPARAM)param);
  767.  
  768.   return 0;
  769. }
  770.  
  771. uint32
  772. TOcApp::ForwardEvent(int eventId, uint32 param)
  773. {
  774.   if (::IsWindow(GetWindow()))
  775.     return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, param);
  776.  
  777.   return 0;
  778. }
  779. #endif
  780.  
  781. //-----------------------------------------------------------------------------
  782. // TOcClassMgr, IBClassMgr implementation for TOcRegistrar
  783. //
  784.  
  785. #if defined(BI_NAMESPACE)
  786. namespace OCF {
  787. #endif
  788.  
  789. class _ICLASS TOcClassMgr : private TUnknown, public IBClassMgr {
  790.   public:
  791.     TOcClassMgr(TComponentFactory cc, uint32 options);
  792.     ~TOcClassMgr();
  793.     ulong _IFUNC   AddRef() ;
  794.     ulong _IFUNC   Release();
  795.  
  796.     void SetApp(TOcApp* app) {OcApp = app;}
  797.  
  798.   private:
  799.     HRESULT _IFUNC QueryInterface(const GUID far& iid, void far*far* iface)
  800.                      {return GetOuter()->QueryInterface(iid, iface);}
  801.     HRESULT _IFUNC ComponentCreate(IUnknown far* far* iface,
  802.                                    IUnknown far* outer, BCID classId);
  803.     HRESULT _IFUNC ComponentInfoGet(IUnknown far* far* info,
  804.                                     IUnknown far* outer, BCID classId);
  805.     // TUnknown virtual overrides
  806.     //
  807.     HRESULT      QueryObject(const IID far& iid, void far* far* iface);
  808.  
  809.     TComponentFactory   OcCallback;    // Callback for creating component
  810.     uint32              Options;       // Options flags from TOcRegistrar
  811.     TOcApp*             OcApp;
  812.     friend class TOcApp;  // could delegate the interface instead...
  813. };
  814.  
  815. #if defined(BI_NAMESPACE)
  816. } // namespace OCF
  817. #endif
  818.  
  819. TOcClassMgr::TOcClassMgr(TComponentFactory cc, uint32 options)
  820. :
  821.   OcCallback(cc),
  822.   Options(options),
  823.         OcApp (0)
  824. {
  825. }
  826.  
  827. TOcClassMgr::~TOcClassMgr()
  828. {
  829. }
  830.  
  831. ulong _IFUNC
  832. TOcClassMgr::AddRef()
  833. {
  834.   return GetOuter()->AddRef();
  835. }
  836.  
  837. ulong _IFUNC
  838. TOcClassMgr::Release()
  839. {
  840.   return GetOuter()->Release();
  841. }
  842.  
  843. //
  844. // IBClassMgr implementation for TOcRegistrar
  845. //
  846. HRESULT _IFUNC
  847. TOcClassMgr::ComponentCreate(IUnknown far* far* retIface, IUnknown far* outer, BCID idClass)
  848. {
  849.   PRECONDITION(idClass && retIface);
  850.  
  851.   *retIface = 0;
  852.   if (!OcCallback)
  853.     return HR_FAIL;
  854.  
  855.   try {
  856.  
  857.     // Test for special condition to force run as an EXE
  858.     //
  859.     void far* v;
  860.     if (outer && !(Options & amExeModule) && outer->QueryInterface(IID_NULL, &v) == HR_NOERROR)
  861.       *retIface = OcCallback(0, Options | amExeMode | amRun, idClass);
  862.     else
  863.       *retIface = OcCallback(outer, Options | amEmbedding, idClass);
  864.     return *retIface ? HR_OK : HR_FAIL;
  865.   }
  866.   catch (...) {  // we can't throw any exception through OLE
  867.                 // if an exception occur shutdown the application if it needs to be so
  868.                 if (OcApp)
  869.         OcApp->ShutdownMaybe ();
  870.  
  871.     return HR_OUTOFMEMORY;  // probably a resource problem, better error code?
  872.   }
  873. }
  874.  
  875. HRESULT _IFUNC
  876. TOcClassMgr::ComponentInfoGet(IUnknown far* far* info, IUnknown far* /*outer*/,
  877.                               BCID /*idClass*/)
  878. {
  879.   *info = 0;
  880.   return HR_FAIL;
  881. }
  882.  
  883. HRESULT
  884. TOcClassMgr::QueryObject(const IID far& iid, void far* far* iface)
  885. {
  886.   HRESULT hr;
  887.  
  888.   // interfaces
  889.      HRSucceeded(hr = IBClassMgr_QueryInterface(this, iid, iface))
  890.   ;
  891.   return hr;
  892. }
  893.  
  894. //----------------------------------------------------------------------------
  895. // IBClassMgr implementation for TOcApp
  896. //
  897.  
  898. HRESULT _IFUNC
  899. TOcApp::ComponentCreate(IUnknown far* far* retIface, IUnknown far* outer, BCID idClass)
  900. {
  901.   return Registrar.OcClassMgr->ComponentCreate(retIface, outer, idClass);
  902. }
  903.  
  904. HRESULT _IFUNC
  905. TOcApp::ComponentInfoGet(IUnknown far* far* info, IUnknown far* outer, BCID idClass)
  906. {
  907.   return Registrar.OcClassMgr->ComponentInfoGet(info, outer, idClass);
  908. }
  909.  
  910. //-----------------------------------------------------------------------------
  911. // TOcRegistrar
  912. //
  913.  
  914. TOcRegistrar::TOcRegistrar(TRegList& regInfo, TComponentFactory callback,
  915.                            string& cmdLine, TRegLink* linkHead,
  916.                            HINSTANCE hInst)
  917. :
  918.   TRegistrar(*new TAppDescriptor(regInfo, callback, cmdLine, hInst, linkHead)),
  919.   BOleInstance(0),
  920.   BCmI(0),
  921.   OcClassMgr(0),
  922.   AppCount(0)
  923. {
  924.   OcClassMgr = new TOcClassMgr(callback, GetOptions());
  925.   OcClassMgr->AddRef();
  926. }
  927.  
  928. TOcRegistrar::~TOcRegistrar()
  929. {
  930.   if (BCmI)
  931.     BCmI->Release();
  932.   if (OcClassMgr)
  933.     OcClassMgr->Release();
  934.   if (BOleInstance > HINSTANCE(32))
  935.     ::FreeLibrary(BOleInstance);
  936. }
  937.  
  938. //
  939. // Create and return a BOle class manager helper interface with 1 ref on it
  940. //
  941. IBClassMgr*
  942. TOcRegistrar::CreateBOleClassMgr()
  943. {
  944.   if (!BOleInstance)
  945.     LoadBOle();
  946.  
  947.   HRESULT PASCAL FAR _export (*createClassMgr)(IUnknown far* far*,
  948.                                                IUnknown far*, IMalloc far*);
  949.   (FARPROC)createClassMgr = ::GetProcAddress(BOleInstance, BOLEBIND);
  950.   if (createClassMgr) {
  951.  
  952.     // Call thru the exported function to get a BOle class manager
  953.     // Don't aggregate it to anything
  954.     //
  955.     IUnknown*   bcm;
  956.     createClassMgr(&bcm, 0, 0);
  957.     if (bcm) {
  958.       IBClassMgr* bcmi;
  959.       bcm->QueryInterface(IID_IBClassMgr, &(LPVOID)bcmi);
  960.       bcm->Release();
  961.       if (bcmi)
  962.         return bcmi;
  963.     }
  964.   }
  965.   TXObjComp::Throw(TXObjComp::xBOleBindFail);
  966.   return 0; // never reached
  967. }
  968.  
  969. //
  970. // Override TRegistrar's GetFactory to provide additional factory support
  971. // using BOle factories
  972. //
  973. void*
  974. TOcRegistrar::GetFactory(const GUID& clsid, const GUID& iid)
  975. {
  976.   void* factory = TRegistrar::GetFactory(clsid, iid);
  977.   if (factory)
  978.     return factory;
  979.  
  980.   if (!BCmI)
  981.     BCmI = CreateBOleClassMgr();
  982.  
  983.   IUnknown* objFactory = 0;
  984.   IBClass* classMgr    = 0;
  985.  
  986.   TRegLink* link = GetAppDescriptor().GetRegLink(clsid);
  987.   if (!link)
  988.     return 0;
  989.  
  990.   TRegList&   regList = link->GetRegList();
  991.   const char* progid = regList[IsOptionSet(amDebug) ? "debugprogid" : "progid" ];
  992.  
  993.   // Create BoleFactory helper object & init it, giving it our OcClassMgr
  994.   // object to work with
  995.   //
  996.   if (!(HRSucceeded(BCmI->ComponentCreate(&objFactory, 0, cidBOleFactory)) &&
  997.       HRSucceeded(objFactory->QueryInterface(IID_IBClass, &(LPVOID)classMgr)) &&
  998.       HRSucceeded(classMgr->Init(false, OleStr(progid), OcClassMgr, reinterpret_cast<BCID>(link))) &&
  999.       HRSucceeded(classMgr->QueryInterface(iid, &factory)))) {
  1000.     if (objFactory)
  1001.       objFactory->Release();
  1002.     if (classMgr)
  1003.       classMgr->Release();
  1004.  
  1005.     return 0;
  1006.   }
  1007.  
  1008.   return factory;
  1009. }
  1010.  
  1011. bool
  1012. TOcRegistrar::CanUnload()
  1013. {
  1014.   TRACEX(OcDll, 1, "CanUnload() AppCount:" << AppCount);
  1015.   return TRegistrar::CanUnload() && AppCount == 0;
  1016. }
  1017.  
  1018. void
  1019. TOcRegistrar::SetApp(TOcApp* app)
  1020. {
  1021.         OcClassMgr->SetApp(app);
  1022. }
  1023.  
  1024. static bool
  1025. sGetFileVersionInfo(const char far* fileName, VS_FIXEDFILEINFO& vInfo)
  1026. {
  1027.   OLECHAR* viBuff;      // version buffer
  1028.   uint32   infoSize;    // Size of version info resource in file
  1029.  
  1030.   // Find out how big the file version info buffer is supposed to be and
  1031.   // create a buffer of that size
  1032.   //
  1033.   uint32 infoHandle;
  1034.   infoSize = ::GetFileVersionInfoSize(OleStr(fileName), &infoHandle);
  1035.   if (infoSize == 0)
  1036.     return false;
  1037.  
  1038.   viBuff = new OLECHAR[(int)infoSize];
  1039.  
  1040.   // Copy the file version info buffer from the file into viBuff
  1041.   //
  1042.   if (::GetFileVersionInfo(OleStr(fileName), 0, infoSize, viBuff)) {
  1043.  
  1044.     // Perform some magic on the phantom buffer to get an actual structure with
  1045.     // the version information
  1046.     //
  1047.     uint vInfoLen;
  1048.     VS_FIXEDFILEINFO far* vInfoPtr;
  1049.     if (::VerQueryValue(viBuff, "\\", &(void far*)vInfoPtr, &vInfoLen)) {
  1050.       vInfo = *vInfoPtr;
  1051.       delete[] viBuff;
  1052.       return true;
  1053.     }
  1054.   }
  1055.   delete[] viBuff;
  1056.   return false;
  1057. }
  1058.  
  1059. //
  1060. // Dynamically load the OcOle Dll, get the one entry point that we need &
  1061. // make the class manager object that we use
  1062. //
  1063. void
  1064. TOcRegistrar::LoadBOle()
  1065. {
  1066.   // Check BOle DLL existance & version first, failing if it is incompatible
  1067.   // (old)
  1068.   //
  1069.   char name[30];
  1070.   OFSTRUCT ofs;
  1071.   ofs.cBytes = sizeof ofs;
  1072.  
  1073. #ifdef NT_PREFERS_UNICODE_INSTEAD_OF_ANSI
  1074. #if defined(BI_PLAT_WIN32)
  1075.   bool winNT = !ToBool(::GetVersion()&0x80000000);
  1076.   if (winNT) // NT platform
  1077.   {
  1078.     lstrcpy(name, BOLEDLLW);
  1079.  
  1080.     // Try the ANSI dll if couldn't find Unicode version
  1081.     if (::OpenFile(name, &ofs, OF_EXIST) == HFILE_ERROR)
  1082.       lstrcpy(name, BOLEDLL);
  1083.   }
  1084.   else
  1085. #endif
  1086. #endif
  1087.     lstrcpy(name, BOLEDLL);
  1088.  
  1089.   if (::OpenFile(name, &ofs, OF_EXIST) >= 0) {
  1090.     VS_FIXEDFILEINFO vInfo;
  1091.     if (!sGetFileVersionInfo(name, vInfo) ||
  1092.         vInfo.dwFileVersionMS < BOLE_FILEVER_MS ||
  1093.           vInfo.dwFileVersionMS == BOLE_FILEVER_MS &&
  1094.           vInfo.dwFileVersionLS < BOLE_FILEVER_LS)
  1095.       TXObjComp::Throw(TXObjComp::xBOleVersFail);
  1096.  
  1097.     BOleInstance = ::LoadLibrary(ofs.szPathName);
  1098.   }
  1099.  
  1100.   // If we failed to load the DLL, throw a general cannot-load exception.
  1101.   // Otherwise get the class manager interface
  1102.   //
  1103.   if (BOleInstance <= HINSTANCE(32))
  1104.     TXObjComp::Throw(TXObjComp::xBOleLoadFail);
  1105. }
  1106.  
  1107. //-----------------------------------------------------------------------------
  1108. // TOcFormatName
  1109. //
  1110.  
  1111. TOcFormatName::TOcFormatName()
  1112. {
  1113. }
  1114.  
  1115. TOcFormatName::TOcFormatName(const char far* name, const char far* resultName,
  1116.                              const char far* id)
  1117. :
  1118.   Name(name),
  1119.   ResultName(resultName),
  1120.   Id(id)
  1121. {
  1122. }
  1123.  
  1124. //----------------------------------------------------------------------------
  1125. // TOcNameList
  1126. //
  1127.  
  1128. TOcNameList::TOcNameList()
  1129. :
  1130.   TICVectorImp<TOcFormatName>(15, 3)
  1131. {
  1132. }
  1133.  
  1134. TOcNameList::~TOcNameList()
  1135. {
  1136.   Clear();
  1137. }
  1138.  
  1139. //
  1140. // Find the format name with the corresponding id
  1141. //
  1142. TOcFormatName*
  1143. TOcNameList::operator [](char far* id)
  1144. {
  1145.   for (uint i = 0; i < Count(); i++) {
  1146.     TOcFormatName* formatName = (*this)[i];
  1147.     if (strcmp(formatName->GetId(), id) == 0)
  1148.       return formatName;
  1149.   }
  1150.  
  1151.   return 0;
  1152. }
  1153.  
  1154. //----------------------------------------------------------------------------
  1155. // TOcInitInfo
  1156. //
  1157.  
  1158. TOcInitInfo::TOcInitInfo(IBContainer far* container)
  1159. :
  1160.   How(ihEmbed),
  1161.   Where(iwNew),
  1162.   Container(container),
  1163.   HIcon(0),
  1164.   Storage(0)
  1165. {
  1166. }
  1167.  
  1168. TOcInitInfo::TOcInitInfo(TOcInitHow how, TOcInitWhere where, IBContainer far* container)
  1169. :
  1170.   How(how),
  1171.   Where(where),
  1172.   Container(container),
  1173.   HIcon(0),
  1174.   Storage(0)
  1175. {
  1176. }
  1177.  
  1178. //----------------------------------------------------------------------------
  1179. // Default FrameHost class implementation for compatibility. Forwards events
  1180. // to FrameWindow using windows messages
  1181. //
  1182.  
  1183. //
  1184. bool
  1185. TOcAppFrameHostMsg::EvOcAppInsMenus(TOcMenuDescr far& sharedMenu)
  1186. {
  1187.   return (bool)ForwardEvent(OC_APPINSMENUS, &sharedMenu);
  1188. }
  1189.  
  1190. bool
  1191. TOcAppFrameHostMsg::EvOcAppMenus(TOcMenuDescr far& md)
  1192. {
  1193.   return (bool)ForwardEvent(OC_APPMENUS, &md);
  1194. }
  1195.  
  1196. bool
  1197. TOcAppFrameHostMsg::EvOcAppProcessMsg(MSG far* msg)
  1198. {
  1199.   return (bool)ForwardEvent(OC_APPPROCESSMSG, msg);
  1200. }
  1201.  
  1202. bool
  1203. TOcAppFrameHostMsg::EvOcAppFrameRect(TRect far* rect)
  1204. {
  1205.   return (bool)ForwardEvent(OC_APPFRAMERECT, rect);
  1206. }
  1207.  
  1208. bool
  1209. TOcAppFrameHostMsg::EvOcAppBorderSpaceReq(TRect far* space)
  1210. {
  1211.   return (bool)ForwardEvent(OC_APPBORDERSPACEREQ, space);
  1212. }
  1213.  
  1214. bool
  1215. TOcAppFrameHostMsg::EvOcAppBorderSpaceSet(TRect far* space)
  1216. {
  1217.   return (bool)ForwardEvent(OC_APPBORDERSPACESET, space);
  1218. }
  1219.  
  1220. void
  1221. TOcAppFrameHostMsg::EvOcAppStatusText(const char far* text)
  1222. {
  1223.   ForwardEvent(OC_APPSTATUSTEXT, text);
  1224. }
  1225.  
  1226. void
  1227. TOcAppFrameHostMsg::EvOcAppRestoreUI()
  1228. {
  1229.   ForwardEvent(OC_APPRESTOREUI);
  1230. }
  1231.  
  1232. void
  1233. TOcAppFrameHostMsg::EvOcAppDialogHelp(TOcDialogHelp far& help)
  1234. {
  1235.   ForwardEvent(OC_APPDIALOGHELP, help);
  1236. }
  1237.  
  1238. bool
  1239. TOcAppFrameHostMsg::EvOcAppShutdown()
  1240. {
  1241.   return (bool)ForwardEvent(OC_APPSHUTDOWN);
  1242. }
  1243.  
  1244. bool
  1245. TOcAppFrameHostMsg::EvOcAppGetAccel(TOcGetAccel far* acc)
  1246. {
  1247.   return ForwardEvent(OC_APPGETACCEL, acc);
  1248. }
  1249.  
  1250. uint32
  1251. TOcAppFrameHostMsg::ForwardEvent(int eventId, const void far* param)
  1252. {
  1253.   HWND hWnd = EvOcGetWindow();
  1254.   if (::IsWindow(hWnd))
  1255.     return ::SendMessage(hWnd, WM_OCEVENT, eventId, (LPARAM)param);
  1256.  
  1257.   return 0;
  1258. }
  1259.  
  1260. uint32
  1261. TOcAppFrameHostMsg::ForwardEvent(int eventId, uint32 param)
  1262. {
  1263.   HWND hWnd = EvOcGetWindow();
  1264.   if (::IsWindow(hWnd))
  1265.     return ::SendMessage(hWnd, WM_OCEVENT, eventId, param);
  1266.  
  1267.   return 0;
  1268. }
  1269.